package app.util.image.calc
{
	import flash.display.*;
	
	public class GrayBitmapData
	{
		//Store int (0 - 255)
		private var data:Array;
		private var width:int;
		private var height:int;
		
		public static function generateFromBinaryBmp(srcData:BinaryBitmapData, 
			markGray:int = 255, unmarkGray:int = 0):GrayBitmapData
		{
			var w:int = srcData.getWidth();
			var h:int = srcData.getHeight();
			var g:GrayBitmapData = new GrayBitmapData(w, h);
			
			for(var x:int = 0; x < w; x++)
			{
				for(var y:int = 0; y < h; y++)
				{
					var gray:int = srcData.isMarked(x, y) ? markGray : unmarkGray;
					g.setGray(x, y, gray);
				}
			}
			
			return g;
		}		
		
		public static function generateFromBmp(srcData:BitmapData):GrayBitmapData
		{
			var w:int = srcData.width;
			var h:int = srcData.height;
			var g:GrayBitmapData = new GrayBitmapData(w, h);
			
			for(var x:int = 0; x < w; x++)
			{
				for(var y:int = 0; y < h; y++)
				{
					var gray:Number = BMPUtility.calcGrayFromColor(srcData.getPixel(x, y));
					g.setGray(x, y, gray);
				}
			}
			
			return g;
		}		
		
		public function GrayBitmapData(w:int, h:int, assignData:Boolean = true)
		{
			this.width = w;
			this.height = h;
			
			if(assignData)
			{
				var size:int = w * h;
				this.data = new Array(size);
			}
		}
	
		public function getWidth():int { return this.width; }
		public function getHeight():int { return this.height; }
		
		public function setGray(x:int, y:int, g:int):void
		{
			if(x < 0 || y < 0 || x >= this.width || y >= this.height) return;
			if(g < 0) g = 0;
			if(g > 255) g = 255;
			this.data[y * this.width + x] = g;
		} 
		
		public function getGray(x:int, y:int):int
		{
			if(x < 0) x = 0;
			if(y < 0) y = 0;
			if(x >= this.width) x = this.width;
			if(y >= this.height) y = this.height;
			return this.data[y * this.width + x] as int;
		}
		
		public function setGrayFromBinaryBitmap(bi:BinaryBitmapData, gray:int):void
		{
			if(bi.getWidth() == this.width && bi.getHeight() == this.height)
			{
				for(var i:int = 0; i < this.width; i++)
				{
					for(var j:int = 0; j < this.height; j++)
					{
						if(bi.isMarked(i, j))
						{
							this.setGray(i, j, gray);
						}
					}
				}
			}
		}
		
		public function add(o:GrayBitmapData, coef:Number = 0.5):GrayBitmapData
		{
			var ret:GrayBitmapData = new GrayBitmapData(this.width, this.height);		
			for(var i:int = 0; i < this.width; i++)
			{
				for(var j:int = 0; j < this.height; j++)
				{
					ret.setGray(i, j, (this.getGray(i, j) + o.getGray(i, j)) * coef);
				}
			}
			
			return ret;
		}
		
		public function minus(o:GrayBitmapData, coef:Number = 0.5):GrayBitmapData
		{
			var ret:GrayBitmapData = new GrayBitmapData(this.width, this.height);		
			for(var i:int = 0; i < this.width; i++)
			{
				for(var j:int = 0; j < this.height; j++)
				{
					ret.setGray(i, j, (this.getGray(i, j) - o.getGray(i, j)) * coef);
				}
			}
			
			return ret;
		}		
		
		public function clone():GrayBitmapData
		{
			var g:GrayBitmapData = new GrayBitmapData(this.width, this.height, false);
			g.data = this.data.concat();
			return g;
		}		
			
		public function toBitmapData():BitmapData
		{
			var bmp:BitmapData = new BitmapData(this.width, this.height, false, 0);
			for(var i:int = 0; i < this.width; i++)
			{
				for(var j:int = 0; j < this.height; j++)
				{
					bmp.setPixel(i, j, BMPUtility.calcColorFromGray(this.getGray(i, j)));
				}
			}
			return bmp;
		}
		
	}
}